#!/bin/bash
#
# Copyright (C) <2018> Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#
# crashlogctl is part of acrn-hypervisor.
#

declare -a CRASHLOG_SERVICES=(
  acrnprobe.service
  usercrash.service
)

declare -a TELEMD_SERVICES=(
  hprobe.timer
  telemd-update-trigger.service
  pstore-clean.service
  pstore-probe.service
  oops-probe.service
  klogscanner.service
  journal-probe.service
  bert-probe.service
)

SCRIPT="$0"
TELEM_DIR=/etc/telemetrics
OPT_OUT_FILE=${TELEM_DIR}/opt-out
USER_CONF_FILE=${TELEM_DIR}/telemetrics.conf
SYSTEM_CONF_FILE=/usr/share/defaults/telemetrics/telemetrics.conf
CRASHLOG_SHARE_DIR=/usr/share/acrn/crashlog
CRASHLOG_SYSTEM_CONF=${CRASHLOG_SHARE_DIR}/40-watchdog.conf
CRASHLOG_SYSCTL_CONF=${CRASHLOG_SHARE_DIR}/80-coredump.conf
CRASHLOG_VAR_DIR=/var/log/crashlog
CRASHLOG_CORE_BACKUP=${CRASHLOG_VAR_DIR}/default_core_pattern
CRASHLOG_S_D_BACKUP=${CRASHLOG_VAR_DIR}/server_delivery_enabled
CRASHLOG_R_R_BACKUP=${CRASHLOG_VAR_DIR}/record_retention_enabled
CRASHLOG_WRK_DIRS_CONF=/usr/lib/tmpfiles.d/acrn-crashlog-dirs.conf
CORE_PATTERN_CONF="/proc/sys/kernel/core_pattern"

create_work_dirs() {
  # Creates dirs if missing, adjust ownership if exists
  systemd-tmpfiles --create ${CRASHLOG_WRK_DIRS_CONF}
}

exit_ok() {
  echo "$1" > /dev/stderr
  exit 0
}

exit_err() {
  echo "$1" > /dev/stderr
  exit 1
}

notice() {
  echo "$1" > /dev/stderr
}

for_each_service() {
  local action=$1 && shift
  local -a array=($*)
  for service in "${array[@]}"; do
    systemctl $action $service
    [ $? -ne 0 ] && notice "Failed to $action ${service}. Continuing..."
  done
}

crashlog_enable() {
  [ -f $OPT_OUT_FILE ] && exit_err "Opt out is enabled. Cannot start services."
  # trigger systemd-tmpfiles work dirs creation
  create_work_dirs

  # backup the default core_pattern
  if [ -f ${CRASHLOG_CORE_BACKUP} ]
  then
      notice "... ${CRASHLOG_CORE_BACKUP} already exist. Do not perform backup"
  else
      cat ${CORE_PATTERN_CONF} > ${CRASHLOG_CORE_BACKUP}
      notice "... Backup core pattern to ${CRASHLOG_CORE_BACKUP}"
  fi

  # copy the configure file
  if [ ! -f ${USER_CONF_FILE} ]
  then
      mkdir -p ${TELEM_DIR}
      cp -v ${SYSTEM_CONF_FILE} ${USER_CONF_FILE}
  fi

  # modify the telemetics configure file
  if grep --quiet server_delivery_enabled=true ${USER_CONF_FILE}
  then
      sed -i "s/server_delivery_enabled=true/server_delivery_enabled=false/g"   ${USER_CONF_FILE}
      echo 1 > ${CRASHLOG_S_D_BACKUP}
      notice "... Set server_delivery_enabled=false in ${USER_CONF_FILE}"
  fi

  if grep --quiet record_retention_enabled=false ${USER_CONF_FILE}
  then
      sed -i "s/record_retention_enabled=false/record_retention_enabled=true/g" ${USER_CONF_FILE}
      echo 1 > ${CRASHLOG_R_R_BACKUP}
      notice "... Set record_retention_enabled=true in ${USER_CONF_FILE}"
  fi

  # Copy watchdog and coredump conf files
  mkdir -p /etc/systemd/system.conf.d
  cp -v ${CRASHLOG_SYSTEM_CONF} /etc/systemd/system.conf.d
  mkdir -p /etc/sysctl.d
  cp -v ${CRASHLOG_SYSCTL_CONF} /etc/sysctl.d

  # Mask telemd services
  for_each_service "mask" ${TELEMD_SERVICES[@]}
  # Enable chrashlog services
  for_each_service "enable" ${CRASHLOG_SERVICES[@]}

  exit_ok "*** Please reboot your system. ***"
}

crashlog_disable() {
  # Disable chrashlog services
  for_each_service "disable" ${CRASHLOG_SERVICES[@]}
  # Unmask telemd services
  for_each_service "unmask"  ${TELEMD_SERVICES[@]}

  rm -v /etc/sysctl.d/${CRASHLOG_SYSCTL_CONF##*/}
  rm -v /etc/systemd/system.conf.d/${CRASHLOG_SYSTEM_CONF##*/}

  # modify the telemetics configure file
  if [ -f ${CRASHLOG_S_D_BACKUP} ]
  then
      sed -i "s/server_delivery_enabled=false/server_delivery_enabled=true/g"   ${USER_CONF_FILE}
      rm -f ${CRASHLOG_S_D_BACKUP}
      notice "... Set server_delivery_enabled=true in ${USER_CONF_FILE}"
  fi

  if [ -f ${CRASHLOG_R_R_BACKUP} ]
  then
      sed -i "s/record_retention_enabled=true/record_retention_enabled=false/g" ${USER_CONF_FILE}
      rm -f ${CRASHLOG_R_R_BACKUP}
      notice "... Set record_retention_enabled=false in ${USER_CONF_FILE}"
  fi

  rm -f ${CRASHLOG_CORE_BACKUP}

  exit_ok "*** Please reboot your system. ***"
}

crashlog_is_active() {
  # check only activation units
  echo "telemprobd :" $(systemctl is-active telemprobd.socket)
  echo "telempostd :" $(systemctl is-active telempostd.path)
  echo "acrnprobe  :" $(systemctl is-active acrnprobe.service)
  echo "usercrash  :" $(systemctl is-active usercrash.service)
}


usage() {
  format='  %-10s %s\n'
  printf "\n"
  printf "%s - Control actions for ACRN crashlog services\n" "$SCRIPT"
  printf "\n"
  printf "$format" "enable"  "Enable the ACRN crashlog services"
  printf "$format" "disable" "Disable the ACRN crashlog services"
  printf "$format" "is-active" "Checks if ACRN crashlog is active"
  printf "\n"
  exit 2
}

if [ $# -ne 1 ]; then
     usage
fi

if [ $EUID -ne 0 ]; then
  exit_err "Must be root to run this command. Exiting..."
fi

SUBCOMMAND=$1

case $SUBCOMMAND in
  enable)
    crashlog_enable ;;
  disable)
    crashlog_disable ;;
  is-active)
    crashlog_is_active ;;
  --help | -h)
    usage ;;
  *)
    notice "Unknown command passed to $SCRIPT"
    usage ;;
esac

exit 0

# vi: ts=8 sw=2 sts=2 et tw=80
